/*
 * cm_hash.h
 *
 *  Created on: 2015年1月29日
 *      各种hash算法
 */

#ifndef CM_HASH_H_
#define CM_HASH_H_

extern inline long RSHash(const void *data, int size)
{
	int b = 378551;
	int a = 63689;
	long hash = 0;
	for (int i = 0; i < size; i++) {
		hash = hash * a + ((const char*) data)[i];
		a = a * b;
	}
	return hash;
}

extern inline long JSHash(const void *data, int size)
{
	long hash = 1315423911;
	for (int i = 0; i < size; i++)
		hash ^= ((hash << 5) + ((const char*) data)[i] + (hash >> 2));
	return hash;
}

extern inline long PJWHash(const void *data, int size)
{
	long BitsInUnsignedInt = (long) (4 * 8);
	long ThreeQuarters = (long) ((BitsInUnsignedInt * 3) / 4);
	long OneEighth = (long) (BitsInUnsignedInt / 8);
	long HighBits = (long) (0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
	long hash = 0;
	long test = 0;
	for (int i = 0; i < size; i++) {
		hash = (hash << OneEighth) + ((const char*) data)[i];
		if ((test = hash & HighBits) != 0)
			hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
	}
	return hash;
}

extern inline long ELFHash(const void *data, int size)
{
	long hash = 0;
	long x = 0;
	for (int i = 0; i < size; i++) {
		hash = (hash << 4) + ((const char*) data)[i];
		if ((x = hash & 0xF0000000L) != 0)
			hash ^= (x >> 24);
		hash &= ~x;
	}
	return hash;
}

extern inline long BKDRHash(const void *data, int size)
{
	long seed = 131; //31131131313131131313etc..
	long hash = 0;
	for (int i = 0; i < size; i++)
		hash = (hash * seed) + ((const char*) data)[i];
	return hash;
}

extern inline long SDBMHash(const void *data, int size)
{
	long hash = 0;
	for (int i = 0; i < size; i++)
		hash = ((const char*) data)[i] + (hash << 6) + (hash << 16)
				- hash;
	return hash;
}

extern inline long DJBHash(const void *data, int size)
{
	long hash = 5381;
	for (int i = 0; i < size; i++)
		hash = ((hash << 5) + hash) + ((const char*) data)[i];
	return hash;
}

extern inline long DEKHash(const void *data, int size)
{
	long hash = size;
	for (int i = 0; i < size; i++)
		hash = ((hash << 5) ^ (hash >> 27)) ^ ((const char*) data)[i];
	return hash;
}

extern inline long BPHash(const void *data, int size)
{
	long hash = 0;
	for (int i = 0; i < size; i++)
		hash = hash << 7 ^ ((const char*) data)[i];
	return hash;
}

extern inline long FNVHash(const void *data, int size)
{
	long fnv_prime = 0x811C9DC5;
	long hash = 0;
	for (int i = 0; i < size; i++) {
		hash *= fnv_prime;
		hash ^= ((const char*) data)[i];
	}
	return hash;
}

extern inline long APHash(const void *data, int size)
{
	long hash = 0xAAAAAAAA;
	for (int i = 0; i < size; i++) {
		if ((i & 1) == 0)
			hash ^= ((hash << 7) ^ ((const char*) data)[i]
					^ (hash >> 3));
		else
			hash ^= (~((hash << 11) ^ ((const char*) data)[i]
					^ (hash >> 5)));
	}
	return hash;
}

#endif /* CM_HASH_H_ */
